﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XSTDZ.ERP.Application.DataContracts;
using XSTDZ.ERP.Core.Repositories;
using XSTDZ.ERP.Domain.Models;
using AutoMapper;
using XSTDZ.ERP.Core.Generator;

namespace XSTDZ.ERP.Application.Implements
{
   public class PermisstionServiceImpl:ApplicationServiceBase,IPermisstionService
    {
       IRepository<Permission> _permissionRepository;
       IRepository<Operation> _operationRepositoty;
       IRepository<UiPermission> _uiPermissionRepositoty;
       IRepository<Role> _roleRepositoty;
       IRepository<RolePermission> _rolePermissionRepositoty;

       IRepository<UserRole> _userRoleRepository;//这里注入，删除用户角色有点不合适,但现在先用到
       public PermisstionServiceImpl(IRepositoryContext context, IRepository<Permission> permission, IRepository<Operation> operation, IRepository<UiPermission> uiPermissionRepositoty, IRepository<Role> roleRepositoty, IRepository<RolePermission> rolePermissionRepositoty, IRepository<UserRole> userRoleRepository)
           : base(context)
       {
           this._permissionRepository = permission;
           this._operationRepositoty = operation;
           this._uiPermissionRepositoty = uiPermissionRepositoty;
           this._roleRepositoty = roleRepositoty;
           this._rolePermissionRepositoty = rolePermissionRepositoty;

           this._userRoleRepository = userRoleRepository;
       }
        #region permission implements
       
       
       public Guid AddPermission(PermissionDto permissionDto)
        {
            var permssion = Mapper.Map<PermissionDto, Permission>(permissionDto);
            permssion.Id = (Guid)new SequentialIdentityGenerator().Next;
            permssion.InitPermission(permssion);
            this._permissionRepository.Add(permssion);
            this.Context.Commit();
            return permssion.Id;
        }

        public void UpdatePermission(PermissionDto permissionDto)
        {
            var permssion = Mapper.Map<PermissionDto, Permission>(permissionDto);
            this._permissionRepository.Update(permssion);
            this.Context.Commit();
        }

        public void DeletePermission(Guid permissionId)
        {
          var permission= this._permissionRepository.GetByKey(permissionId);
         //   this._uiPermissionRepositoty.Remove(p=>permission.Permissions.Select(m=>m.Id).ToArray().Contains(p.Id));
            this._permissionRepository.Remove(p => p.ParentID == permissionId);
            this._permissionRepository.Remove(p => p.Id == permissionId);
            this.Context.Commit();
        }

        public PermissionDto GetPermission(Guid permissionId)
        {
            var permission = this._permissionRepository.Get(p => p.Id == permissionId);
            var permissionDto = Mapper.Map<Permission, PermissionDto>(permission);
            return permissionDto;
        }

        public IEnumerable<PermissionDto> GetAllPermission()
        {
            var permissionlst = this._permissionRepository.GetAll();
            var permissiona= Mapper.Map<IEnumerable<Permission>, IEnumerable<PermissionDto>>(permissionlst);
            return permissiona;
        }

        public IEnumerable<PermissionDto> GetAllPermission(Guid parentPermissionId)
        {
            var permissionlst = this._permissionRepository.GetAll(p => p.Id == parentPermissionId);
            return Mapper.Map<IEnumerable<Permission>, IEnumerable<PermissionDto>>(permissionlst);
        }

       
       #endregion
        #region operation implements

        public Guid Add(OperationDto operationDto)
        {
            var operation = Mapper.Map<OperationDto, Operation>(operationDto);
            operation.Id = (Guid)new SequentialIdentityGenerator().Next;
            operation.InitOperation();
            this._operationRepositoty.Add(operation);
            this.Context.Commit();
            return operation.Id;
        }
        #region 这个访问只针对初始化数据用，并不提供对外接口
        public void Add(IList<Operation> operations)
        {
        //    var operations = Mapper.Map<IList<OperationDto>, IList<Operation>>(operationDto);
            operations.Each(o => o.InitOperation());
            this._operationRepositoty.Add(operations);
            this.Context.Commit();

        }
        #endregion
        public  void Update(OperationDto operationDto)
        {
            var operation = Mapper.Map<OperationDto, Operation>(operationDto);
            operation.InitOperation();
            this._operationRepositoty.Update(operation);
            this.Context.Commit();
        }
        public void Update(Guid operationId, Guid permissionId)
        {
          var operation=  _operationRepositoty.GetByKey(operationId);
          operation.PermissionID = permissionId;
          this._operationRepositoty.Update(operation);
          this.Context.Commit();
        }
        public void DeleteOperation(Guid operationId)
        {
            this._operationRepositoty.Remove(o => o.ParentID == operationId ||o.Id == operationId);
            this.Context.Commit();
        }
        public IEnumerable<OperationDto> GetAllOperations()
        {
           var operations= this._operationRepositoty.GetAll();
           var operationDtos= Mapper.Map<IEnumerable<Operation>,IEnumerable<OperationDto>>(operations);
           return operationDtos;
        }

        public OperationDto GetOperation(Guid id)
        {
            var operation = this._operationRepositoty.Get(o => o.Id == id);
            var operationDto = Mapper.Map<Operation, OperationDto>(operation);
            return operationDto;
        }

        public OperationDto GetOperation(string code)
        {
            var operation = this._operationRepositoty.Get(o => o.Code == code);
            var operationDto = Mapper.Map<Operation, OperationDto>(operation);
            return operationDto;
        }

        #endregion
        #region UiPermission implements

        public void AddUiPermission(PermissionDto permissionDto, UiPermissionDto uiPermissionDto)
        {
            var isExist = this._permissionRepository.Exists(p => p.Id == permissionDto.ParentId);
            if (isExist)
            {
                var permssion = Mapper.Map<PermissionDto, Permission>(permissionDto);
                permssion.Id = (Guid)new SequentialIdentityGenerator().Next;
                permssion.InitPermission(permssion);
                permssion.Level = 2;
                permssion.Order = 0;
                permssion.IsEnableEdit = true;

                var uiPermssion = Mapper.Map<UiPermissionDto, UiPermission>(uiPermissionDto);
                uiPermssion.Id = permssion.Id;
                uiPermssion.InitUiPermission();
                permssion.UiPermission = uiPermssion;

                this._permissionRepository.Add(permssion);
                this.Context.Commit();
            }
        }

        public void UpdateUiPermission(PermissionDto permissionDto)
        {
            var permssion = Mapper.Map<PermissionDto, Permission>(permissionDto);
            permssion.Level = 2;
            permssion.Order = 0;
            permssion.UiPermission.Id = permssion.Id;
            permssion.UiPermission.InitUiPermission();

            this._permissionRepository.Update(permssion);
            this._uiPermissionRepositoty.Update(permssion.UiPermission);
            this.Context.Commit();
        }

        public Guid AddUiPermission(Guid permissionId, UiPermissionDto uiPermissionDto)
        {
            var permission = this._permissionRepository.Get(p => p.Id == permissionId);//一级数据行
            if (permission.Id==permissionId)
            {
                var tempPermission = new Permission() { 
                     Id=(Guid)new SequentialIdentityGenerator().Next,
                     Level = Convert.ToSByte(permission.Level + 1),
                     Name = permission.Name,
                     Code = permission.Code,
                     Controller = permission.Controller,
                     Action = permission.Action,
                     Order = permission.Order,
                     ParentID = permission.ParentID,
                     Url = permission.Url
                };
                var uiPermssion = Mapper.Map<UiPermissionDto, UiPermission>(uiPermissionDto);
                uiPermssion.Id = tempPermission.Id;
                uiPermssion.InitUiPermission();

                tempPermission.UiPermission=uiPermssion;
                this._permissionRepository.Add(tempPermission);
                this.Context.Commit();
                return tempPermission.Id;
            }
            return Guid.Empty;
        }
        public void UpdateUiPermission(UiPermissionDto uiPermissionDto)
        {
            var permission = this._permissionRepository.GetByKey(uiPermissionDto.Id);
            permission.UiPermission.ClientId = uiPermissionDto.ClientId;
            permission.UiPermission.ImagePath = uiPermissionDto.ImagePath;
            permission.UiPermission.IsMenu = uiPermissionDto.IsMenu;
            permission.UiPermission.InitUiPermission();
             this._permissionRepository.Update(permission);
            this.Context.Commit();
        }
        public UiPermissionDto GetUiPermission(Guid uiPermissionId)
        {
            var uiPermission = this._uiPermissionRepositoty.Get(p => p.Id == uiPermissionId);
            return Mapper.Map<UiPermission, UiPermissionDto>(uiPermission);
        }
        public void DeleteUiPermission(Guid uiPermissionId)
        {
            this._uiPermissionRepositoty.Remove(u => u.Id == uiPermissionId);
            this._permissionRepository.Remove(u => u.Id == uiPermissionId);
            this.Context.Commit();
        }
        public IEnumerable<UiPermissionDto> GetUiPermissions(Guid permissionId)
        {
            var uiPermission = this._uiPermissionRepositoty.GetAll(p => p.Id == permissionId);
            return Mapper.Map<IEnumerable<UiPermission>, IEnumerable<UiPermissionDto>>(uiPermission);
        }
        public IEnumerable<UiPermissionDto> GetUiPermissions()
        {
            var uiPermission = this._uiPermissionRepositoty.GetAll();
            return Mapper.Map<IEnumerable<UiPermission>, IEnumerable<UiPermissionDto>>(uiPermission);
        }
       public IEnumerable<UiPermissionDto> GetUiPermissions(string controllerName, string actionName)
        {
            var permission = this._permissionRepository.Get(p => p.Controller.ToUpper() == controllerName.ToUpper() &&p.Action.ToUpper()==actionName.ToUpper()&&  p.Level==1);
            if (permission == null)
            {
                return null;
            }
            var permissionlst = this._permissionRepository.GetAll(t => t.ParentID == permission.Id && t.Level != 1);
            var uiPermissions = permissionlst.Select(p => p.UiPermission).ToList();
            return Mapper.Map<IEnumerable<UiPermission>, IEnumerable<UiPermissionDto>>(uiPermissions);
        }
        #endregion
        #region role implements
        public Guid AddRole(RoleDto roleDto)
        {
            var role = Mapper.Map<RoleDto, Role>(roleDto);
            if (roleDto.Id == null || roleDto.Id.Equals(Guid.Empty))
            {
                role.Id = (Guid)new SequentialIdentityGenerator().Next;
            }
            else
            {
                role.Id = roleDto.Id;
            }
            role= role.AddPermissions(roleDto.PermissionIds);
            this._roleRepositoty.Add(role);
            if (role.RolePermissions != null && role.RolePermissions.Count() != 0)
            {
                this._rolePermissionRepositoty.Add(role.RolePermissions);
            }
            this.Context.Commit();
            return role.Id;
        }

        public void UpdateRole(RoleDto roleDto)
        {
             var role = Mapper.Map<RoleDto, Role>(roleDto);
             this._roleRepositoty.Update(role);
             this.Context.Commit();
        }

        public void DeleteRole(Guid roleId)//以下删除是有顺序的
        {
            this._userRoleRepository.Remove(t => t.RoleID == roleId);// 删除用户角色(用户与角色关系 供应删除角色时使用)
            this._rolePermissionRepositoty.Remove(t => t.RoleID == roleId);//角色权限
            this._roleRepositoty.Remove(r => r.Id == roleId);//角色
            this.Context.Commit();
        }

        public RoleDto GetRole(Guid roleId)
        {
            var role = this._roleRepositoty.Get(r => r.Id == roleId);
            return Mapper.Map<Role, RoleDto>(role);
        }

        public IEnumerable<RoleDto> GetAllRole()
        {
            var role = this._roleRepositoty.GetAll();
            return Mapper.Map<IEnumerable<Role>,IEnumerable< RoleDto>>(role);
        }
        #endregion


        public void AddOrUpdatePermissionsOfRole(Guid RoleId, IEnumerable<Guid> uiPermissionIds, IEnumerable<Guid> permissionIds, string typeName)
        {
            var ps = this._permissionRepository.GetAll(t => permissionIds.Contains(t.Id)).Select(t => t.ParentID).Distinct().ToList();
            ps = ps.Where(t => !permissionIds.ToArray().Contains(t)).ToList();

            var tagetlist=permissionIds.ToList();
            tagetlist.AddRange(ps);
            var role = this._roleRepositoty.GetByKey(RoleId);
            if (typeName==null||typeName.Trim() == "全部")
            {
                role.ClearPermissions().AddPermissionIds(tagetlist);
            }
            else
            {
               var rolePermissions= role.RolePermissions.Where(t => t.Permission.TypeName.Substring(1, t.Permission.TypeName.Length - 1) == typeName.Trim()).ToList();
               rolePermissions.Clear();
                role.AddPermissionIds(tagetlist);
            }
           
            this._roleRepositoty.Update(role);
            this.Context.Commit();
        }


        public IList<Guid> GetSelectPermissionsOfRole(Guid RoleId)
        {
            return this._roleRepositoty.GetByKey(RoleId).RolePermissions.Select(r => r.PermissionID.GetValueOrDefault()).ToList();
           
        }



       
    }
}
